/*------------------------------------------------------------------------------
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
*
* Distributable under the terms of either the Apache License (Version 2.0) or
* the GNU Lesser General Public License, as specified in the LICENSE file.
------------------------------------------------------------------------------*/
#ifndef _lucene_search_PhraseQuery_
#define _lucene_search_PhraseQuery_

#if defined(_LUCENE_PRAGMA_ONCE)
# pragma once
#endif

#include "Query.hpp"
#include "../util/VoidList.hpp"

CL_NS_DEF(index)
class Term;
CL_NS_END

CL_NS_DEF(search)
// A Query that matches documents containing a particular sequence of terms.
// This may be combined with other terms with a {@link BooleanQuery}.
class PhraseQuery: public Query
{
private:
	CL_NS(util)::CLVector < int32_t, CL_NS(util)::Deletor::DummyInt32 > positions;
	int32_t slop;

	const UChar *field;
	CL_NS(util)::CLVector < CL_NS(index)::Term* > terms;

	/*
	class PhraseWeight: public Weight
	{
	private:
		Searcher* searcher;
		float_t value;
		float_t idf;
		float_t queryNorm;
		float_t queryWeight;
		PhraseQuery* _this;
	public:
		PhraseWeight(Searcher* searcher, PhraseQuery* _this);
		~PhraseWeight();
		UChar *toString();

		Query* getQuery();
		float_t getValue();

		float_t sumOfSquaredWeights();
		void normalize(float_t queryNorm);
		//Scorer* scorer(CL_NS(index)::IndexReader* reader);
		//void explain(CL_NS(index)::IndexReader* reader, int32_t doc, Explanation* ret);
		UChar *toString(UChar *f);
		bool equals(PhraseWeight* o);
	};
	friend class PhraseWeight;
	*/

protected:
	//Weight* _createWeight(Searcher* searcher);
	PhraseQuery(const PhraseQuery& clone);
public:
	//Constructor
	PhraseQuery();

	//Destructor
	~PhraseQuery();

	//! Init string declarations
	static void InitStringDecl();

	//Returns the string "PhraseQuery"
	const UChar *getQueryName() const;
	static const UChar *getClassName();

	//Sets the number of other words permitted between words in query phrase.
	//If zero, then this is an exact phrase search.  For larger values this works
	//like a WITHIN or NEAR operator.
	//
	//The slop is in fact an edit-distance, where the units correspond to
	//moves of terms in the query phrase out of position.  For example, to switch
	//the order of two words requires two moves (the first move places the words
	//atop one another), so to permit re-orderings of phrases, the slop must be
	//at least two.
	//
	//More exact matches are scored higher than sloppier matches, thus search
	//results are sorted by exactness.
	//
	//The slop is zero by default, requiring exact matches.
	void setSlop(const int32_t s) {
		slop = s;
	}

	//Returns the slop.  See setSlop().
	int32_t getSlop() const {
		return slop;
	}

	//Adds a term to the end of the query phrase.
	void add(CL_NS(index)::Term* term);
	void add(CL_NS(index)::Term* term, int32_t position);

	//Returns the sum of squared weights
	//float_t sumOfSquaredWeights(Searcher* searcher);

	//Normalizes the Weight
	void normalize(const float_t norm);

	//Scorer* scorer(CL_NS(index)::IndexReader* reader);

	//added by search highlighter
	//CL_NS(index)::Term** getTerms() const;
	//void getPositions(CL_NS(util)::Array<int32_t>& result) const;

	const UChar *getFieldName() const {
		return field;
	}

	//! Prints a user-readable version of this query
	UChar *toString(const UChar *f) const;

	Query* clone() const;
	bool equals(CL_NS(search)::Query *) const;

	size_t hashCode() const;

	/**
	* Search the query and get the entry set result
	* @memory Caller must clean up
	*/
	Atoll::EntrySet* Search(Atoll::Searcher *inSearcher);
};
CL_NS_END
#endif
